package jbpmguice;

import com.google.common.base.Preconditions;
import jbpmguice.workflow.InjectableTestAction;
import org.jbpm.JbpmConfiguration;
import org.jbpm.JbpmContext;
import org.jbpm.graph.def.Action;
import org.jbpm.graph.def.ProcessDefinition;
import org.jbpm.graph.exe.ProcessInstance;
import org.jbpm.graph.exe.Token;
import org.jbpm.instantiation.Delegation;
import org.jbpm.jpdl.xml.JpdlXmlReader;

import java.io.InputStream;
import java.io.InputStreamReader;

public class JBPMTestUtils {
    public JBPMTestUtils() {
    }

    public JbpmConfiguration loadProcessDefinitionFromConfiguration(String processDefinitionResource) {
        JbpmConfiguration jbpmConfiguration = JbpmConfiguration.getInstance();
        JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
        InputStream resourceAsStream = getClass().getResourceAsStream(processDefinitionResource);
        Preconditions.checkNotNull(resourceAsStream);

        //Assert.assertNotNull(resourceAsStream);
        JpdlXmlReader s = new JpdlXmlReader(new InputStreamReader(resourceAsStream));
        ProcessDefinition definition = s.readProcessDefinition();
        jbpmContext.deployProcessDefinition(definition);
        ProcessInstance instance = definition.createProcessInstance();
        jbpmContext.save(instance);

        Preconditions.checkNotNull(instance);
        //Assert.assertNotNull(instance);
        jbpmContext.close();
        return jbpmConfiguration;
    }

    public void runTestScenario(String processName, JbpmConfiguration config) {
        JbpmContext jbpmContext = config.createJbpmContext();
        try {
            ProcessInstance processInstance = jbpmContext.getGraphSession().findProcessDefinition(processName, 1).createProcessInstance();
            jbpmContext.save(processInstance);
            Preconditions.checkNotNull(processInstance);
            ProcessDefinition processDefinition = processInstance.getProcessDefinition();
            Token token = processInstance.getRootToken();
            Preconditions.checkState(processDefinition.getStartState() == token.getNode());
            Action action;
            do {
                processInstance.signal();
                action = processInstance.getRootToken().getNode().getAction();
                if (action != null) {
                    // Singleton check
                    Delegation actionDelegation = action.getActionDelegation();
                    InjectableTestAction injectedActionHandler = (InjectableTestAction) actionDelegation.getInstance();
                    int executionCounter = injectedActionHandler.getExecutionCounter();
                    Preconditions.checkState(
                            executionCounter > 0,
                            "Singleton Check failed. " + executionCounter + " > 0 ");
                }
            } while (action != null);
        } finally {
            jbpmContext.close();
        }
    }
}